/*
 * Copyright 2002-2021 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.web.servlet.handler;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

import javax.servlet.DispatcherType;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.logging.Log;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactoryUtils;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.core.Ordered;
import org.springframework.core.log.LogDelegateFactory;
import org.springframework.http.server.RequestPath;
import org.springframework.lang.Nullable;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.PathMatcher;
import org.springframework.web.HttpRequestHandler;
import org.springframework.web.context.request.WebRequestInterceptor;
import org.springframework.web.context.request.async.WebAsyncManager;
import org.springframework.web.context.request.async.WebAsyncUtils;
import org.springframework.web.context.support.WebApplicationObjectSupport;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.CorsProcessor;
import org.springframework.web.cors.CorsUtils;
import org.springframework.web.cors.DefaultCorsProcessor;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.servlet.HandlerExecutionChain;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.HandlerMapping;
import org.springframework.web.util.ServletRequestPathUtils;
import org.springframework.web.util.UrlPathHelper;
import org.springframework.web.util.pattern.PathPattern;
import org.springframework.web.util.pattern.PathPatternParser;

/**
 * {@link org.springframework.web.servlet.HandlerMapping}实现的抽象基类.
 * 支持排序、默认handler、handler interceptor, 包括由路径模式映射的handler interceptor.
 *
 * <p>注意: 这个基类<i>不</i>支持{@link #PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE}的公开.
 * 对该属性的支持取决于具体的子类, 通常基于request URL映射.
 *
 * @author Juergen Hoeller
 * @author Rossen Stoyanchev
 * @since 07.04.2003
 * @see #getHandlerInternal
 * @see #setDefaultHandler
 * @see #setInterceptors
 * @see org.springframework.web.servlet.HandlerInterceptor
 */
public abstract class AbstractHandlerMapping extends WebApplicationObjectSupport
		implements HandlerMapping, Ordered, BeanNameAware {

	/** 用于request映射的专用"hidden" logger. */
	protected final Log mappingsLogger =
			LogDelegateFactory.getHiddenLog(HandlerMapping.class.getName() + ".Mappings");


	@Nullable
	private Object defaultHandler;

	@Nullable
	private PathPatternParser patternParser;

	private UrlPathHelper urlPathHelper = new UrlPathHelper();

	private PathMatcher pathMatcher = new AntPathMatcher();

	private final List<Object> interceptors = new ArrayList<>();

	private final List<HandlerInterceptor> adaptedInterceptors = new ArrayList<>();

	@Nullable
	private CorsConfigurationSource corsConfigurationSource;

	private CorsProcessor corsProcessor = new DefaultCorsProcessor();

	private int order = Ordered.LOWEST_PRECEDENCE;  // default: same as non-Ordered

	@Nullable
	private String beanName;


	/**
	 * 设置此handler映射的默认handler.
	 * 如果没有找到特定的映射, 将返回此handler.
	 * <p>默认值为{@code null}, 表示没有默认handler.
	 */
	public void setDefaultHandler(@Nullable Object defaultHandler) {
		this.defaultHandler = defaultHandler;
	}

	/**
	 * 返回此handler映射的默认handler, 如果没有, 则返回{@code null}.
	 */
	@Nullable
	public Object getDefaultHandler() {
		return this.defaultHandler;
	}

	/**
	 * 启用预解析的{@link PathPattern}s作为与{@link AntPathMatcher}匹配的String pattern
	 * 的替代方案. 语法基本相同, 但{@code PathPattern}语法更适合web application, 其实现也更高效.
	 * <p>此属性与以下其他属性互斥, 当设置此属性时, 这些属性将被有效忽略:
	 * <ul>
	 * <li>{@link #setAlwaysUseFullPath} -- {@code PathPatterns}总是使用完整路径, 而忽略
	 * servletPath/pathInfo, 后者经过decoded和部分规范化, 因此与
	 * {@link HttpServletRequest#getRequestURI() requestURI}不可比较.
	 * <li>{@link #setRemoveSemicolonContent} -- 出于路径匹配的目的, {@code PathPatterns}
	 * 总是忽略分号内容, 但路径参数仍然可以通过{@code @MatrixVariable}在controller中使用.
	 * <li>{@link #setUrlDecode} -- {@code PathPatterns}一次匹配一个decoded的路径段, 并且
	 * 从不需要完整的decoded路径, 这可能会由于decoded的保留字符而导致问题.
	 * <li>{@link #setUrlPathHelper} -- 请求路径由{@link org.springframework.web.servlet.DispatcherServlet
	 * DispatcherServlet}或{@link org.springframework.web.filter.ServletRequestPathFilter
	 * ServletRequestPathFilter}使用{@link ServletRequestPathUtils}全局预解析, 并保存在request
	 * 属性中以供重用.
	 * <li>{@link #setPathMatcher} -- pattern被解析为{@code PathPatterns}, 并使用它来代替与
	 * {@code PathMatcher}匹配的字符串.
	 * </ul>
	 * <p>默认情况下, 此选项未设置.
	 * @param patternParser 要使用的parser
	 * @since 5.3
	 */
	public void setPatternParser(PathPatternParser patternParser) {
		this.patternParser = patternParser;
	}

	/**
	 * 返回{@link #setPatternParser(PathPatternParser) configured}
	 * {@code PathPatternParser}, 或 {@code null}.
	 * @since 5.3
	 */
	@Nullable
	public PathPatternParser getPatternParser() {
		return this.patternParser;
	}

	/**
	 * 配置的{@code UrlPathHelper}上相同属性的快捷方式.
	 * <p><strong>注意:</strong> 设置{@link #setPatternParser(PathPatternParser)}时,
	 * 此属性与其互斥.
	 * @see org.springframework.web.util.UrlPathHelper#setAlwaysUseFullPath(boolean)
	 */
	@SuppressWarnings("deprecation")
	public void setAlwaysUseFullPath(boolean alwaysUseFullPath) {
		this.urlPathHelper.setAlwaysUseFullPath(alwaysUseFullPath);
		if (this.corsConfigurationSource instanceof UrlBasedCorsConfigurationSource) {
			((UrlBasedCorsConfigurationSource) this.corsConfigurationSource).setAlwaysUseFullPath(alwaysUseFullPath);
		}
	}

	/**
	 * 基础{@code UrlPathHelper}上相同属性的快捷方式.
	 * <p><strong>注意:</strong> 设置{@link #setPatternParser(PathPatternParser)}时,
	 * 此属性与其互斥.
	 * @see org.springframework.web.util.UrlPathHelper#setUrlDecode(boolean)
	 */
	@SuppressWarnings("deprecation")
	public void setUrlDecode(boolean urlDecode) {
		this.urlPathHelper.setUrlDecode(urlDecode);
		if (this.corsConfigurationSource instanceof UrlBasedCorsConfigurationSource) {
			((UrlBasedCorsConfigurationSource) this.corsConfigurationSource).setUrlDecode(urlDecode);
		}
	}

	/**
	 * 基础{@code UrlPathHelper}上相同属性的快捷方式.
	 * <p><strong>注意:</strong> 在设置{@link #setPatternParser(PathPatternParser)}时,
	 * 此属性与其互斥.
	 * @see org.springframework.web.util.UrlPathHelper#setRemoveSemicolonContent(boolean)
	 */
	@SuppressWarnings("deprecation")
	public void setRemoveSemicolonContent(boolean removeSemicolonContent) {
		this.urlPathHelper.setRemoveSemicolonContent(removeSemicolonContent);
		if (this.corsConfigurationSource instanceof UrlBasedCorsConfigurationSource) {
			((UrlBasedCorsConfigurationSource) this.corsConfigurationSource).setRemoveSemicolonContent(removeSemicolonContent);
		}
	}

	/**
	 * 配置UrlPathHelper以用于解析lookup path.
	 * <p><strong>注意:</strong> 当设置{@link #setPatternParser(PathPatternParser)}时,
	 * 此属性与其互斥.
	 */
	public void setUrlPathHelper(UrlPathHelper urlPathHelper) {
		Assert.notNull(urlPathHelper, "UrlPathHelper must not be null");
		this.urlPathHelper = urlPathHelper;
		if (this.corsConfigurationSource instanceof UrlBasedCorsConfigurationSource) {
			((UrlBasedCorsConfigurationSource) this.corsConfigurationSource).setUrlPathHelper(urlPathHelper);
		}
	}

	/**
	 * 返回{@link #setUrlPathHelper configured} {@code UrlPathHelper}.
	 */
	public UrlPathHelper getUrlPathHelper() {
		return this.urlPathHelper;
	}

	/**
	 * 配置要使用的PathMatcher.
	 * <p><strong>注意:</strong> 在设置{@link #setPatternParser(PathPatternParser)}时,
	 * 此属性与其互斥, 并被忽略.
	 * <p>默认情况下, 这是{@link AntPathMatcher}.
	 * @see org.springframework.util.AntPathMatcher
	 */
	public void setPathMatcher(PathMatcher pathMatcher) {
		Assert.notNull(pathMatcher, "PathMatcher must not be null");
		this.pathMatcher = pathMatcher;
		if (this.corsConfigurationSource instanceof UrlBasedCorsConfigurationSource) {
			((UrlBasedCorsConfigurationSource) this.corsConfigurationSource).setPathMatcher(pathMatcher);
		}
	}

	/**
	 * 返回{@link #setPathMatcher configured} {@code PathMatcher}.
	 */
	public PathMatcher getPathMatcher() {
		return this.pathMatcher;
	}

	/**
	 * 将interceptor设置为应用于此handler映射所映射的所有handler.
	 * Set the interceptors to apply for all handlers mapped by this handler mapping.
	 * <p>支持的interceptor类型有{@link HandlerInterceptor}, {@link WebRequestInterceptor},
	 * 和{@link MappedInterceptor}. 映射interceptor仅适用于与其路径模式匹配的请求URL.
	 * 在初始化过程中, 映射的interceptor bean也会按类型进行检测.
	 * @param interceptors handler interceptor的数组
	 * @see #adaptInterceptor
	 * @see org.springframework.web.servlet.HandlerInterceptor
	 * @see org.springframework.web.context.request.WebRequestInterceptor
	 * @see MappedInterceptor
	 */
	public void setInterceptors(Object... interceptors) {
		this.interceptors.addAll(Arrays.asList(interceptors));
	}

	/**
	 * 设置"全局"CORS配置映射. 第一个匹配的URL模式确定了要使用的{@code CorsConfiguration},
	 * 然后是与所选handler的{@code CorsConfiguration}一起使用的
	 * {@link CorsConfiguration#combine(CorsConfiguration).
	 * <p>这与{@link #setCorsConfigurationSource(CorsConfigurationSource)}是互斥的.
	 * @since 4.2
	 * @see #setCorsProcessor(CorsProcessor)
	 */
	public void setCorsConfigurations(Map<String, CorsConfiguration> corsConfigurations) {
		if (CollectionUtils.isEmpty(corsConfigurations)) {
			this.corsConfigurationSource = null;
			return;
		}
		UrlBasedCorsConfigurationSource source;
		if (getPatternParser() != null) {
			source = new UrlBasedCorsConfigurationSource(getPatternParser());
			source.setCorsConfigurations(corsConfigurations);
		}
		else {
			source = new UrlBasedCorsConfigurationSource();
			source.setCorsConfigurations(corsConfigurations);
			source.setPathMatcher(this.pathMatcher);
			source.setUrlPathHelper(this.urlPathHelper);
		}
		setCorsConfigurationSource(source);
	}

	/**
	 * 为"全局"CORS配置设置{@code CorsConfigurationSource}. 由源确定的
	 * {@code CorsConfiguration}是
	 * {@link CorsConfiguration#combine(CorsConfiguration) combined}, 带有所选
	 * handler的{@code CorsConfiguration}.
	 * <p>这与{@link #setCorsConfigurations(Map)}是互斥的.
	 * @since 5.1
	 * @see #setCorsProcessor(CorsProcessor)
	 */
	public void setCorsConfigurationSource(CorsConfigurationSource source) {
		Assert.notNull(source, "CorsConfigurationSource must not be null");
		this.corsConfigurationSource = source;
		if (source instanceof UrlBasedCorsConfigurationSource) {
			((UrlBasedCorsConfigurationSource) source).setAllowInitLookupPath(false);
		}
	}

	/**
	 * 返回{@link #setCorsConfigurationSource(CorsConfigurationSource)
	 * configured} {@code CorsConfigurationSource}(如果有).
	 * @since 5.3
	 */
	@Nullable
	public CorsConfigurationSource getCorsConfigurationSource() {
		return this.corsConfigurationSource;
	}

	/**
	 * 配置一个自定义{@link CorsProcessor}, 用于为request应用匹配的{@link CorsConfiguration}.
	 * <p>默认情况下使用{@link DefaultCorsProcessor}.
	 * @since 4.2
	 */
	public void setCorsProcessor(CorsProcessor corsProcessor) {
		Assert.notNull(corsProcessor, "CorsProcessor must not be null");
		this.corsProcessor = corsProcessor;
	}

	/**
	 * 返回已配置的{@link CorsProcessor}.
	 */
	public CorsProcessor getCorsProcessor() {
		return this.corsProcessor;
	}

	/**
	 * 指定此HandlerMapping bean的顺序值.
	 * <p>默认值为{@code Ordered.LOWEST_PRECEDENCE}, 表示未排序.
	 * @see org.springframework.core.Ordered#getOrder()
	 */
	public void setOrder(int order) {
		this.order = order;
	}

	@Override
	public int getOrder() {
		return this.order;
	}

	@Override
	public void setBeanName(String name) {
		this.beanName = name;
	}

	protected String formatMappingName() {
		return this.beanName != null ? "'" + this.beanName + "'" : getClass().getName();
	}


	/**
	 * 初始化interceptor.
	 * @see #extendInterceptors(java.util.List)
	 * @see #initInterceptors()
	 */
	@Override
	protected void initApplicationContext() throws BeansException {
		extendInterceptors(this.interceptors);
		detectMappedInterceptors(this.adaptedInterceptors);
		initInterceptors();
	}

	/**
	 * 子类可以覆盖的扩展钩子, 在给定配置的interceptor的情况 下注册额外的interceptor
	 * (参见{@link #setInterceptors}).
	 * <p>将在{@link #initInterceptors()}将指定的interceptor适配到
	 * {@link HandlerInterceptor}实例之前调用.
	 * <p>默认实现为空.
	 * @param interceptors 配置的interceptor列表(从不{@code null}), 允许在现有
	 * interceptor之前和之后添加更多的interceptor.
	 */
	protected void extendInterceptors(List<Object> interceptors) {
	}

	/**
	 * 检测类型为{@link MappedInterceptor}的bean, 并将它们添加到映射的interceptor列表中.
	 * <p>这是在可能通过{@link #setInterceptors}提供的任何{@link MappedInterceptor}之外
	 * 调用的, 默认情况下会添加当前context及其祖先中{@link MappedInterceptor}类型的所有bean.
	 * 子类可以覆盖和完善此策略.
	 * @param mappedInterceptors 要添加到的空list
	 */
	protected void detectMappedInterceptors(List<HandlerInterceptor> mappedInterceptors) {
		mappedInterceptors.addAll(BeanFactoryUtils.beansOfTypeIncludingAncestors(
				obtainApplicationContext(), MappedInterceptor.class, true, false).values());
	}

	/**
	 * 初始化指定的interceptor, 使{@link WebRequestInterceptor}s适应{@link HandlerInterceptor}.
	 * @see #setInterceptors
	 * @see #adaptInterceptor
	 */
	protected void initInterceptors() {
		if (!this.interceptors.isEmpty()) {
			for (int i = 0; i < this.interceptors.size(); i++) {
				Object interceptor = this.interceptors.get(i);
				if (interceptor == null) {
					throw new IllegalArgumentException("Entry number " + i + " in interceptors array is null");
				}
				this.adaptedInterceptors.add(adaptInterceptor(interceptor));
			}
		}
	}

	/**
	 * 将给定interceptor对象调整为{@link HandlerInterceptor}.
	 * <p>默认情况下, 支持的interceptor类型为{@link HandlerInterceptor}和
	 * {@link WebRequestInterceptor}. 每个给定的{@link WebRequestInterceptor}
	 * 都用{@link WebRequestHandlerInterceptorAdapter}包装.
	 * @param interceptor the interceptor
	 * @return interceptor下行或适用于HandlerInterceptor
	 * @see org.springframework.web.servlet.HandlerInterceptor
	 * @see org.springframework.web.context.request.WebRequestInterceptor
	 * @see WebRequestHandlerInterceptorAdapter
	 */
	protected HandlerInterceptor adaptInterceptor(Object interceptor) {
		if (interceptor instanceof HandlerInterceptor) {
			return (HandlerInterceptor) interceptor;
		}
		else if (interceptor instanceof WebRequestInterceptor) {
			return new WebRequestHandlerInterceptorAdapter((WebRequestInterceptor) interceptor);
		}
		else {
			throw new IllegalArgumentException("Interceptor type not supported: " + interceptor.getClass().getName());
		}
	}

	/**
	 * 将及鞥过调整的interceptor返回为{@link HandlerInterceptor}数组.
	 * @return {@link HandlerInterceptor HandlerInterceptor}s的数组,
	 * 如果没有, 则为{@code null}
	 */
	@Nullable
	protected final HandlerInterceptor[] getAdaptedInterceptors() {
		return (!this.adaptedInterceptors.isEmpty() ?
				this.adaptedInterceptors.toArray(new HandlerInterceptor[0]) : null);
	}

	/**
	 * 将所有配置的{@link MappedInterceptor}s作为数组返回.
	 * @return {@link MappedInterceptor}s的数组, 如果没有, 则为{@code null}
	 */
	@Nullable
	protected final MappedInterceptor[] getMappedInterceptors() {
		List<MappedInterceptor> mappedInterceptors = new ArrayList<>(this.adaptedInterceptors.size());
		for (HandlerInterceptor interceptor : this.adaptedInterceptors) {
			if (interceptor instanceof MappedInterceptor) {
				mappedInterceptors.add((MappedInterceptor) interceptor);
			}
		}
		return (!mappedInterceptors.isEmpty() ? mappedInterceptors.toArray(new MappedInterceptor[0]) : null);
	}


	/**
	 * 如果此{@code HandlerMapping}已被{@link #setPatternParser enabled}
	 * 使用解析的{@code PathPattern}s, 则返回"true".
	 */
	@Override
	public boolean usesPathPatterns() {
		return getPatternParser() != null;
	}

	/**
	 * 为给定的request查找一个handler, 如果找不到特定的handler, 则返回默认handler.
	 * @param request 当前HTTP请求
	 * @return 对应的handler实例或默认handler
	 * @see #getHandlerInternal
	 */
	@Override
	@Nullable
	public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
		Object handler = getHandlerInternal(request);
		if (handler == null) {
			handler = getDefaultHandler();
		}
		if (handler == null) {
			return null;
		}
		// Bean name or resolved handler?
		if (handler instanceof String) {
			String handlerName = (String) handler;
			handler = obtainApplicationContext().getBean(handlerName);
		}

		// Ensure presence of cached lookupPath for interceptors and others
		if (!ServletRequestPathUtils.hasCachedPath(request)) {
			initLookupPath(request);
		}

		HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);

		if (logger.isTraceEnabled()) {
			logger.trace("Mapped to " + handler);
		}
		else if (logger.isDebugEnabled() && !DispatcherType.ASYNC.equals(request.getDispatcherType())) {
			logger.debug("Mapped to " + executionChain.getHandler());
		}

		if (hasCorsConfigurationSource(handler) || CorsUtils.isPreFlightRequest(request)) {
			CorsConfiguration config = getCorsConfiguration(handler, request);
			if (getCorsConfigurationSource() != null) {
				CorsConfiguration globalConfig = getCorsConfigurationSource().getCorsConfiguration(request);
				config = (globalConfig != null ? globalConfig.combine(config) : config);
			}
			if (config != null) {
				config.validateAllowCredentials();
			}
			executionChain = getCorsHandlerExecutionChain(request, executionChain, config);
		}

		return executionChain;
	}

	/**
	 * 查找给定request的handler, 如果找不到特定的handler, 则返回{@code null}.
	 * 这个方法被{@link #getHandler}调用; 如果设置了默认handler, 则{@code null}返回值
	 * 将导致默认handler.
	 * <p>对CORS pre-flight 请求, 该方法应该返回一个匹配, 不是针对pre-flight请求, 而是针对基于
	 * URL路径的预期实际请求, 来自"Access-Control-Request-Method" header的HTTP方法, 以及来自
	 * "Access-Control-Request-Headers" header的header, 从而允许通过
	 * {@link #getCorsConfiguration(Object, HttpServletRequest)}获得CORS配置.
	 * <p>注意: 这个方法也可以返回一个pre-built {@link HandlerExecutionChain}, 将handler
	 * 对象与动态确定的interceptor结合在一起. 静态指定的interceptor将被合并到这样一个现有链中.
	 * @param request 当前HTTP请求
	 * @return 对应的handler实例, 如果没有找到, 则为{@code null}
	 * @throws Exception 如果有内部错误
	 */
	@Nullable
	protected abstract Object getHandlerInternal(HttpServletRequest request) throws Exception;

	/**
	 * 初始化要用于请求映射的路径.
	 * <p>当已解析的模式是{@link #usesPathPatterns() enabled}时,
	 * {@link org.springframework.web.servlet.DispatcherServlet}或
	 * {@link org.springframework.web.filter.ServletRequestPathFilter}应该在外部对解析的
	 * {@code RequestPath}进行{@link ServletRequestPathUtils#parseAndCache(HttpServletRequest) parsed}.
	 * <p>否则, 对于通过{@code PathMatcher}进行的字符串模式匹配, 此方法路径为
	 * {@link UrlPathHelper#resolveAndCacheLookupPath resolved}.
	 * @since 5.3
	 */
	protected String initLookupPath(HttpServletRequest request) {
		if (usesPathPatterns()) {
			request.removeAttribute(UrlPathHelper.PATH_ATTRIBUTE);
			RequestPath requestPath = ServletRequestPathUtils.getParsedRequestPath(request);
			String lookupPath = requestPath.pathWithinApplication().value();
			return UrlPathHelper.defaultInstance.removeSemicolonContent(lookupPath);
		}
		else {
			return getUrlPathHelper().resolveAndCacheLookupPath(request);
		}
	}

	/**
	 * 为给定的handler构建一个{@link HandlerExecutionChain}, 包括通用的interceptor.
	 * <p>默认实现使用给定的handler、handler映射的公共interceptor以及与当前请求URL匹配的任何
	 * {@link MappedInterceptor MappedInterceptors}构建标准{@link HandlerExecutionChain}.
	 * <p><b>注意:</b> 传入的handler对象可以是原始handler或pre-built {@link HandlerExecutionChain}.
	 * 此方法应该显式处理这两种情况, 要么构建新的{@link HandlerExecutionChain}, 要么扩展现有链.
	 * <p>要简单地在自定义子类中添加interceptor, 可以考虑调用{@code super.getHandlerExecutionChain(handler, request)}
	 * 并在返回的链对象上调用{@link HandlerExecutionChain#addInterceptor}.
	 * @param handler 已解析的handler实例(从不为{@code null})
	 * @param request 当前HTTP请求
	 * @return HandlerExecutionChain (从不为{@code null})
	 * @see #getAdaptedInterceptors()
	 */
	protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) {
		HandlerExecutionChain chain = (handler instanceof HandlerExecutionChain ?
				(HandlerExecutionChain) handler : new HandlerExecutionChain(handler));

		for (HandlerInterceptor interceptor : this.adaptedInterceptors) {
			if (interceptor instanceof MappedInterceptor) {
				MappedInterceptor mappedInterceptor = (MappedInterceptor) interceptor;
				if (mappedInterceptor.matches(request)) {
					chain.addInterceptor(mappedInterceptor.getInterceptor());
				}
			}
			else {
				chain.addInterceptor(interceptor);
			}
		}
		return chain;
	}

	/**
	 * 如果此handler存在{@link CorsConfigurationSource}, 则返回{@code true}.
	 * @since 5.2
	 */
	protected boolean hasCorsConfigurationSource(Object handler) {
		if (handler instanceof HandlerExecutionChain) {
			handler = ((HandlerExecutionChain) handler).getHandler();
		}
		return (handler instanceof CorsConfigurationSource || this.corsConfigurationSource != null);
	}

	/**
	 * 检索给定handler的CORS配置.
	 * @param handler 要检查的handler(从不为{@code null}).
	 * @param request 当前的request.
	 * @return handler的CORS配置, 如果没有, 则为{@code null}
	 * @since 4.2
	 */
	@Nullable
	protected CorsConfiguration getCorsConfiguration(Object handler, HttpServletRequest request) {
		Object resolvedHandler = handler;
		if (handler instanceof HandlerExecutionChain) {
			resolvedHandler = ((HandlerExecutionChain) handler).getHandler();
		}
		if (resolvedHandler instanceof CorsConfigurationSource) {
			return ((CorsConfigurationSource) resolvedHandler).getCorsConfiguration(request);
		}
		return null;
	}

	/**
	 * 更新HandlerExecutionChain进行与cors相关的处理.
	 * <p>对于pre-flight请求, 默认实现将使用一个简单的HttpRequestHandler替换所选handler,
	 * 该handler调用配置的{@link #setCorsProcessor}.
	 * <p>对于实际的请求, 默认实现插入一个HandlerInterceptor, 用于进行与CORS相关的检查并添加
	 * CORS headers.
	 * @param request 当前的request
	 * @param chain the handler chain
	 * @param config 使用的CORS配置(可能是{@code null})
	 * @since 4.2
	 */
	protected HandlerExecutionChain getCorsHandlerExecutionChain(HttpServletRequest request,
			HandlerExecutionChain chain, @Nullable CorsConfiguration config) {

		if (CorsUtils.isPreFlightRequest(request)) {
			HandlerInterceptor[] interceptors = chain.getInterceptors();
			return new HandlerExecutionChain(new PreFlightHandler(config), interceptors);
		}
		else {
			chain.addInterceptor(0, new CorsInterceptor(config));
			return chain;
		}
	}


	private class PreFlightHandler implements HttpRequestHandler, CorsConfigurationSource {

		@Nullable
		private final CorsConfiguration config;

		public PreFlightHandler(@Nullable CorsConfiguration config) {
			this.config = config;
		}

		@Override
		public void handleRequest(HttpServletRequest request, HttpServletResponse response) throws IOException {
			corsProcessor.processRequest(this.config, request, response);
		}

		@Override
		@Nullable
		public CorsConfiguration getCorsConfiguration(HttpServletRequest request) {
			return this.config;
		}
	}


	private class CorsInterceptor implements HandlerInterceptor, CorsConfigurationSource {

		@Nullable
		private final CorsConfiguration config;

		public CorsInterceptor(@Nullable CorsConfiguration config) {
			this.config = config;
		}

		@Override
		public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
				throws Exception {

			// Consistent with CorsFilter, ignore ASYNC dispatches
			WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
			if (asyncManager.hasConcurrentResult()) {
				return true;
			}

			return corsProcessor.processRequest(this.config, request, response);
		}

		@Override
		@Nullable
		public CorsConfiguration getCorsConfiguration(HttpServletRequest request) {
			return this.config;
		}
	}

}
